package com.qianfeng.websocket;


//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼            BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  


import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.config.annotation.EnableWebSocket;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by jackiechan on 2021/6/10 09:40
 * 我们说这个类是用来接收 websocket 请求的
 * 凭什么我们说是就是,因为我们实现了一些接口
 * @author jackiechan
 */


//TODO 我们主动给客户端发消息,需要服务端知道客户端在哪,客户端在哪呢?
//TODO 我们会有很多个不同的客户端,比如张三给李四发消息,如何找到李四的客户端(会话)

@Component //单例对象 ///
@EnableWebSocket//启用 websocket
public class MyWebSocketClient implements WebSocketHandler {

    private Map<String, WebSocketSession> allClients = new HashMap<>();

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 当我们的客户端和服务端建立 websocket 连接之后执行
     * @param webSocketSession 当前建立的会话连接
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        System.err.println("恭喜武汉x同学获得2021第一位知道高考成绩的成就");
        //当我们保存的时候发现需要唯一的标识,也就是说保存张三的会话的时候需要知道是张三
        //我们约定请求地址的最后一位是唯一标识
        String uri = webSocketSession.getUri().toString();
        String name = uri.substring(uri.lastIndexOf("/") + 1);//从地址的最后一个/后面开始切割,要最后一位数据,就是我们的名字
        allClients.put(name, webSocketSession);//保存了会话
    }

    /**
     * 服务端收到了客户端发送的消息
     * @param webSocketSession 发送消息的客户端的会话连接
     * @param webSocketMessage 发送的消息内容
     * @throws Exception
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        System.err.println("收到你发给小姐姐的骚扰信息了");
        //我们现在的目的是 比如说收到了张三给李四发的消息, 我们需要找到李四的会话,然后发过去
        //我们怎么知道消息是发给谁的,所以我们也要定义消息的格式,要求发送方必须按照这个格式发送内容
        //比如我们定义一个 json  {"touser":"lisi","msg":"你好"}

        String json = (String) webSocketMessage.getPayload();
        Map map = objectMapper.readValue(json, Map.class);//解析数据
        String touser = (String) map.get("touser");//获取到收消息的用户
        String msg = (String) map.get("msg");//获取到消息
        WebSocketSession session = allClients.get(touser);//获取到收消息的人的会话
        if (session != null&&session.isOpen()) {
            //要确保对方在线
            //我们约定请求地址的最后一位是唯一标识
            String uri = webSocketSession.getUri().toString();
            String name = uri.substring(uri.lastIndexOf("/") + 1);//从发送方的会话中获取发送方的名字
            session.sendMessage(new TextMessage("收到了来自于"+name+"的消息,内容是:"+msg));
        }else{
            //对方不在线,给发送者回一个消息
            webSocketSession.sendMessage(new TextMessage("对方暂时无法接通"));
        }

    }

    /**
     * 出现异常的时候执行
     * @param webSocketSession 出现问题的会话连接
     * @param throwable
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {

    }

    /**
     * 客户端和服务端关闭了连接
     * @param webSocketSession 当前要关闭的会话连接
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        System.err.println("你和客服小姐姐中断联系了");
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}
